/*
 * @Author: yangzonglong
 * @Date: 2021-05-25 14:43:54
 * @version: v1.0.0
 * @Descripttion: table
 * @LastEditors: 871387321@qq.com 871387321@qq.com
 * @LastEditTime: 2023-11-15 13:09:44
 * @Auditor:
 */
import React, { useCallback, useState, useImperativeHandle, forwardRef, useEffect, useRef, useMemo } from 'react';
import { Button, Row, Col, Table, Input, message, Pagination, InputRef } from 'antd';
import { ActionText, } from '@library';
import { moneyFormat } from '@library/components/table/util';
import Upload from './upload/Upload';
import * as XLSX from 'xlsx/xlsx.mjs';
import moment from 'moment';
import exportXlsx from '@library/utils/exportXlsx/exportXlsx';
import Icon from '@library/components/icon/Icon';
import update from 'immutability-helper';
import FileModal from './_ImportFileModal';
// import Qs from 'query-string';
import { textReplaceStr } from '../../util';
import useQueryControlWrap from '../../hooks/useQueryControlWrap';
import { ControlMap, DataItemProps, ColumnType, TableProps } from './config';
import { getServer } from './util';
import { CanvasItemProps, ActionFieldType } from './../../interface';
import evalScriptText from './../../eval';
import cls from './table.module.scss';
import { ShowModalOptionsType } from './../../interface';
import { ColumnsType } from 'antd/lib/table';

const Column = Table.Column,
  designDefData = [{ id: '1' }],
  scrollStyle = { x: 'max-content' },
  colStyle = {
    fontWeight: 500,
  },
  rowStyle: React.CSSProperties = {
    marginBottom: '0',
    lineHeight: '48px',
    padding: '0 4px',
    marginTop: '8px',
  };
const T = window.$app.t;
const linkArray = ['input', 'dataLinkCombox', 'dataLink', 'inputNum'];
const requiredStyle = {
  color: '#ff4d4f'
};
const showFiledArray = ['dataLink', 'dataLinkCombox'];
const showLabelArray = ['radio', 'checkbox', 'select'];
const formatArray = ['datePicker'];
const inputStyle: React.CSSProperties = {
  width: '100%',
  position: 'absolute',
  top: '0',
  bottom: '0',
  left: '0',
  cursor: 'pointer',
  visibility: 'hidden',
};

const PAGE_SIZE = 20;
const pageSizeOptions = [
  "20",
  "50",
  "100",
  "200",
  "500",
  "800",
  "1000",
  "2000",
];

interface RefProps {
  getData(): any;
  getDataNotCheck(): any;
}

export interface CompoentTableProps extends CanvasItemProps {
  validateRequired(): void;
  inEditInitVal?: boolean;
  tableProps: TableProps;
  formItemProps: any;
  scriptsChangeData: Object;
  sendData: any;
  onValuesChange?(id: string, data: any, isBtn?: boolean, changeKey?: string): void; // dataSource有变化时执行
  title?: string;
  titleEn?: string;
  name?: string;
  print?: boolean;
  printBorder?: boolean;
  hideAdd?: boolean;
  hideDelete?: boolean;
  scrollY?: number;
  scriptText?: string;
  initialValue?: any[];
  disabled?: boolean; // 为true时 预览不允许操作
  editColumns?: string[]; // column 启用
  required?: boolean;
  exportFlag?: boolean;
  enviromentConfig?: any;
}

type CustomOptionType = Record<'addBtn' | 'importBtn' | 'exportBtn' | 'columnDelete', {
  hide: boolean;
  style?: Function;
}>;

type SummaryType = {
  name: string;
  value: string | number;
  colSpan?: number;
  editable?: boolean;
  disabled?: boolean;
  style?: React.CSSProperties;
};

export default forwardRef((props: CompoentTableProps, ref: React.Ref<RefProps>) => {

  // const query = Qs.parseUrl(window.location.href).query;

  const isInitial = useRef(false);
  const currChangeLineIndex = useRef<number | undefined>();
  const currChangeDataIndex = useRef<any>('');
  const isSetInitialValue = useRef(false);
  const inputRef = useRef<HTMLInputElement>(null);

  const [page, setPage] = useState(1);
  const [pageSize, setPageSize] = useState(PAGE_SIZE);
  const [visible, setVisible] = useState(false);
  const [flag, setFlag] = useState(false);
  const [dataSource, setDataSource] = useState<DataItemProps[]>([]);
  const [realColumns, setRealColumns] = useState<any[]>([]);
  const [customOptions, srtCustomOptions] = useState<CustomOptionType>({} as any);
  const [summaryData, setSummaryData] = useState<SummaryType[][]>([]);
  const [summaryValue, setSummaryValue] = useState<Record<string, string | number>>({});
  const [summaryStyles, setSummaryStyles] = useState<Record<string, React.CSSProperties>>({});
  const [required, setRequired] = useState(false);
  const [columnsRequired, setColumnsRequired] = useState({});
  const summaryValueRef = useRef({});
  const { enviromentConfig, domComplete, inEditInitVal, hideAdd, hideDelete, tableProps, title, titleEn, initialValue, disabled, scriptsChangeData, getCurrInterceptors, scriptText, exportScriptText, onValuesChange, controlRefs, setActionFiledMap, validateFields, ...canvasProps } = props;

  // eslint-disable-next-line react-hooks/rules-of-hooks
  if (canvasProps.isDesign) useQueryControlWrap(canvasProps.id, '', domComplete);

  const _columns = useMemo(() => {
    if (!Object.keys(columnsRequired).length) return realColumns;

    return realColumns.map(item => {
      if (typeof columnsRequired[item.dataIndex] === 'boolean') {
        return { ...item, options: { ...item.options, required: columnsRequired[item.dataIndex] } };
      }
      return item;
    });
  }, [columnsRequired, realColumns]);

  useImperativeHandle(ref, () => ({
    getSummaryValue: () => summaryValueRef.current,
    setSummaryValue(coverSummaryValue: Record<string, string | number>) {
      summaryValueRef.current = {
        ...summaryValueRef.current,
        ...coverSummaryValue
      };
      setSummaryValue(summaryValueRef.current);
    },
    setSummaryStyle(styles: Record<string, React.CSSProperties>) {
      const newSummaryStyles = { ...summaryStyles };

      for (let name in styles) {
        newSummaryStyles[name] = {
          ...newSummaryStyles[name],
          ...styles[name]
        };
      }

      setSummaryStyles(newSummaryStyles);
    },
    setSummary(data: SummaryType[][]) {
      const summaryValue = {};
      const summaryStyle = {};

      data.forEach(arr => {
        arr.forEach(item => {
          if (item.name) {
            summaryValue[item.name] = item.value;
            summaryStyle[item.name] = item.style || {};
          }
        });
      });

      setSummaryData(data);
      setSummaryValue(summaryValue);
      setSummaryStyles(summaryStyle);
      summaryValueRef.current = summaryValue;
    },
    setCustomOptions(options: CustomOptionType) {
      srtCustomOptions(options);
    },
    getDataNotCheck() {
      return JSON.parse(JSON.stringify(dataSource));
    },
    setData(data: any) {
      if (!data) return;
      isInitial.current = false;
      setDataSource((data || []).map((item: any, index: number) => {
        return {
          ...item,
          id: item.id || `$_${index}`
        };
      }));
    },
    getData() {
      const handleDataSource: DataItemProps[] = [];
      const requiredColumns = _columns.filter((item) => item.options.required);

      if (required && dataSource.length === 0) {
        message.warning(`表格数据不能为空`);
        return false;
      }

      for (let item of dataSource) {
        const copyItem = { ...item };

        requiredColumns.forEach((column) => {
          const dataIndex = column.dataIndex as string;

          if (!copyItem[dataIndex]) {
            copyItem[dataIndex] = column.options.initialValue || copyItem[dataIndex];
          }
        });

        for (let k in copyItem) {
          const column = _columns.find((item) => item.dataIndex === k);

          if (column?.options.required) {
            if (column.type !== 'inputNum') {
              if (!copyItem[k]) {
                message.warning(`请将表格每一行的${column.title}填写完整`);
                return false;
              }
            } else {
              if (!copyItem[k] && copyItem[k] !== 0) {
                message.warning(`请将表格每一行的${column.title}填写完整`);
                return false;
              }
            }
          }
        }

        if (copyItem?.id?.includes('$_')) {
          (copyItem as any).id = undefined;
          delete copyItem._changeIndex;
        }

        handleDataSource.push(copyItem);
      }


      return handleDataSource;
    },
    getColumns() {
      return JSON.parse(JSON.stringify(tableProps.columns));
    },
    setColumns(columns: any[]) {
      setFlag(true);
      setRealColumns(columns);
    },
    setTableRequired(required: boolean | undefined, columnsRequired?: Record<string, boolean>) {
      if (typeof required === 'boolean') setRequired(required);
      if (columnsRequired && Object.values(columnsRequired).filter(item => typeof item === 'boolean').length) {
        setColumnsRequired(columnsRequired);
      }
    }
  }));

  useEffect(() => {
    setRequired(!!props.required);
  }, [props.required]);

  useEffect(() => {
    if (flag === false && tableProps.columns) {
      setRealColumns(tableProps.columns);
    }
  }, [tableProps.columns, flag]);

  useEffect(() => {
    if (initialValue && !isSetInitialValue.current) {
      let _v = Array.isArray(initialValue) ? [...initialValue] : [...JSON.parse(initialValue)];
      setDataSource(_v.map((item, index) => ({ ...item, id: item.id || `$_${index}` })));
      isSetInitialValue.current = true;
    } else if (tableProps.initialValue) {
      let _v = tableProps.initialValue;
      Array.isArray(_v) && setDataSource(_v?.map((item, index) => ({ ...item, id: item.id || `$_${index}` })));
    }
  }, [initialValue, tableProps.initialValue]);

  // dataSource变化 valuesChange
  useEffect(() => {
    if (isInitial.current) {
      const changeKey = currChangeDataIndex.current ? props.name + '.' + currChangeDataIndex.current : props.name;
      if (dataSource.length) {
        dataSource.forEach(item => {
          item._changeIndex = currChangeLineIndex.current;
        });
        props.onValuesChange?.(props.name!, dataSource, false, changeKey);
      } else {
        props.onValuesChange?.(props.name!, dataSource, false, changeKey);
      }

      isInitial.current = false;
    }
  }, [dataSource, props.name, props.onValuesChange]);


  const onChange = useCallback((e: React.BaseSyntheticEvent) => {
    const files = e.target.files;
    const file = files?.[0];

    if (!files) return;

    const bindLink = realColumns?.filter(item => item?.options?.bindName && (item.type === 'input' || item.type === 'inputNum'));

    const bindObj: any = {};
    bindLink.forEach((item) => {
      if (bindObj[item.options.bindName]) {
        bindObj[item.options.bindName].push({
          showFiled: item.options.showFiled,
          dataIndex: item.dataIndex
        });
      } else {
        bindObj[item.options.bindName] = [
          {
            showFiled: item.options.showFiled,
            dataIndex: item.dataIndex
          }
        ];
      }
    });

    const cloumns = realColumns?.filter(item => item.type === 'dataLink');

    const dateColumns = realColumns?.filter(item => item.type === "datePicker").map(item => item.dataIndex);

    const lovList = cloumns.reduce((all: any[], now: any) => {

      return all.concat([{
        dataIndex: now.dataIndex,
        url: now.options.serviceType === 'APP'
          ? `/bk/api/${now.options.serviceModuleCode}/${now.options.modulesName}/find`
          : now.options.modulesUrl,
        showFieldName: now.options.showFieldName,
        filedShowName: now.options.filedShowName,
        rowSelectionType: now.radio ? 'checkbox' : 'radio'
      }]);
    }, []);

    const reader = new FileReader();
    reader.readAsBinaryString(file);

    reader.onload = async function (e) {
      let wb = XLSX.read(e?.target?.result, {
        type: 'binary',
        cellText: false,
        cellDates: true
      });
      let data: any[] = XLSX.utils.sheet_to_json(wb.Sheets[wb.SheetNames[0]], { raw: false, dateNF: "yyyy-mm-dd" });

      data = data.map((item, index) => ({ ...item, id: `$_${+(new Date())}${index}` }));

      if (data.length >= 2) {
        data.splice(0, 1);

        lovList.forEach(item => {
          let _query: any[] = [];
          data.forEach(ele => {
            if (item.rowSelectionType === 'checkbox') {
              _query = _query.concat(ele[item.dataIndex]?.split(','));
            } else {
              _query.push(ele[item.dataIndex]);
            }
          });
          item.query = _query;
        });

        data = data.map(item => {
          let obj = { ...item };
          for (let k in item) {
            if (dateColumns.includes(k)) {
              obj[k] = moment(item[k]).format('YYYY/MM/DD');
            }
          }
          return obj;
        });

        for (const iterator of lovList) {
          const showFieldName = typeof iterator.showFieldName === 'string' ? iterator.showFieldName : iterator.showFieldName.value;
          const res = await getServer(iterator.url, { where: { [showFieldName]: { $in: iterator.query } } });

          const sourceObj = res?.rows.reduce((all: any, now: any) => {
            return { ...all, [now?.[showFieldName]]: now };
          }, {});

          data = data.map((element: any) => {
            if (iterator.rowSelectionType === 'checkbox') {

              let value = {};
              const indexs = element[iterator.dataIndex]?.split(',') || [];

              indexs.forEach((item: any, index: number) => {
                if (index === 0) {
                  value = { ...(sourceObj[item] || {}) };
                } else {
                  for (let k in value) {
                    if (value.hasOwnProperty(k) && (typeof value[k] === 'string' || typeof value[k] === 'number')) {
                      value[k] = (value[k] + ' ' + sourceObj[item]?.[k]);
                    }
                  }
                }
              });

              const linkArr = bindObj[iterator.dataIndex] || [];
              const linkData = linkArr.reduce((_all: any, _now: any) => {
                return { ..._all, [_now.dataIndex]: value?.[_now.showFiled] };
              }, {});

              element[iterator.dataIndex] = element[iterator.dataIndex].replaceAll(',', ' ');

              return {
                ...iterator.filedShowName?.reduce((all: any, now: any) => {
                  return { ...all, [now.value]: value?.[now.value], ...linkData };
                }, {}), ...element
              };
            } else {
              const value = { ...(sourceObj[element[iterator.dataIndex]] || {}) };
              const linkArr = bindObj[iterator.dataIndex] || [];
              const linkData = linkArr.reduce((_all: any, _now: any) => {
                return { ..._all, [_now.dataIndex]: value?.[_now.showFiled] };
              }, {});

              return {
                ...iterator.filedShowName?.reduce((all: any, now: any) => {
                  return { ...all, [now.value]: value?.[now.value], ...linkData };
                }, {}), ...element
              };
            }

          });


        }

        if (inputRef.current) inputRef.current.value = (null as any);
        isInitial.current = true;
        currChangeDataIndex.current = '';
        setDataSource(data.map(item => {
          item._isImport = true;
          return item;
        }));

      }
    };
  }, [realColumns]);

  const downLoadTemplate = async () => {
    const columns = realColumns.reduce((all: ColumnType[], now: ColumnType) => {
      if (now.disabled || now.type === "code" || now.type === 'upload' || now.exportFlag === false) {
        return all;
      }
      return all.concat([{ ...now, width: 20 }]);
    }, []);

    if (exportScriptText) {
      evalScriptText({
        scriptText: exportScriptText as string,
        extra: { columns, originalColumns: realColumns },
        next: ({ columns, fileName }: { fileName?: string; columns: ColumnsType[]; }) => {
          exportXlsx({
            fileName: fileName || '导入模板.xlsx',
            columns: columns.map((item: any) => {
              return { ...item, title: item.options.required ? `* ${item.title}` : item.title };
            }),
            dataSource: []
          });
        }
      });
    } else {
      exportXlsx({
        fileName: '导入模板.xlsx',
        columns: columns.map((item: ColumnType) => {
          return { ...item, title: item.options.required ? `* ${item.title}` : item.title };
        }),
        dataSource: []
      });
    }
  };

  const addLine = useCallback(() => {
    currChangeDataIndex.current = '';

    let data = realColumns?.reduce((all, now) => {
      console.log(now);
      if (now.type === "select") {
        let _v = now?.options?.dataSource?.filter((item: any) => item.checked);
        return _v.length ? { ...all, [now.dataIndex as string]: _v[0]?.value } : all;
      } else if (now.type === 'textArea') {
        return now?.options?.[localStorage.i18nextLng === 'en' ? 'initialValueEn' : 'initialValue'] ? { ...all, [now.dataIndex as string]: now?.options?.[localStorage.i18nextLng === 'en' ? 'initialValueEn' : 'initialValue'] } : all;
      }
      return now?.options?.initialValue ? { ...all, [now.dataIndex as string]: now?.options?.initialValue } : all;
    }, {});

    setDataSource(
      update(dataSource.map(item => {
        delete item._isImport;
        return item;
      }), {
        $push: [
          {
            id: '$_' + (+new Date()),
            ...data,
            _isCreate: true
          },
        ],
      })
    );

    currChangeLineIndex.current = dataSource.length;
    isInitial.current = true;
  }, [dataSource, realColumns]);

  const delLine = (id: string, currPageDataLen: number) => {
    currChangeDataIndex.current = '';

    const index = dataSource.findIndex((item) => item.id === id);
    const newDataSource = update(dataSource.map(item => {
      delete item._isImport;
      return item;
    }), {
      $splice: [[index, 1]],
    });

    setDataSource(newDataSource);

    currChangeLineIndex.current = index;
    isInitial.current = true;
    if (currPageDataLen === 1 && page > 1) setPage(page - 1);
  };

  const onChangeLine = (record: DataItemProps, v: any, k: string, isInitPeriod?: boolean) => {
    currChangeDataIndex.current = k;
    const index = dataSource.findIndex((item) => item.id === record.id);
    setDataSource(prev => prev.map((item, i) => i === index ? ({ ...item, [k]: v, _isImport: undefined }) : item));

    // 初始化不去通知form change
    if (!isInitPeriod) isInitial.current = true;
    currChangeLineIndex.current = index;
  };

  const render = (text: string, record: any, column: ColumnType) => {
    const dataIndex = column.dataIndex as string;
    const index = dataSource.findIndex((item) => item.id === record.id);

    if (column.type === 'text') {
      const columnCustomOptions = customOptions?.[column.dataIndex as string] || {};
      const styles = columnCustomOptions?.style ? columnCustomOptions.style(record) : {};
      styles.textAlign = column?.textAlign || 'left';
      styles.display = 'inline-block';
      styles.width = '100%';
      return (
        <span style={styles}>
          {record[dataIndex] ?? column?.options?.text}
        </span>
      );
    }

    if (record._disabled === true || (Array.isArray(record._disabled) && record._disabled.includes(column.dataIndex)) || (disabled && !canvasProps.isDesign && !props.editColumns?.includes(dataIndex))) {
      if (showFiledArray.includes(column.type)) return record[dataIndex];
      else if (showLabelArray.includes(column.type)) {
        let _temp = column.options?.dataSource.filter((item: any) =>
          Array.isArray(record[dataIndex]) ? record[dataIndex].includes(item.value) : record[dataIndex] === item.value
        );

        let str = '';
        _temp.forEach((element: any, index: number) => {
          const _l = (localStorage.i18nextLng === 'en' ? element?.labelEn : element.label) || element.label;
          str += index === _temp.length - 1 ? _l : _l + '、';
        });

        return str;
      } else if (formatArray.includes(column.type)) {
        return record[dataIndex] ? moment(record[dataIndex]).format(column?.options?.format || window.$app.MOMENT_FORMAT_DATE) : '';
      } else if (column.type === 'inputNum') {
        return <span style={{ textAlign: column.textAlign, display: 'inline-block', width: '100%' }}>{record[dataIndex] || record[dataIndex] === 0 ? column.options?.formatterMoney ? moneyFormat(record[dataIndex]) : typeof column.options?.precision === 'number' ? Number(record[dataIndex]).toFixed(column.options?.precision) : Number(record[dataIndex]) : ''}</span>;
      } else if (column.type === 'statusTransfer') {
        try {
          const statusTransfer = JSON.parse(column[localStorage.i18nextLng === 'en' ? 'statusTransferEn' : 'statusTransfer']) || {};
          return statusTransfer[record[dataIndex]] ?? T(record[dataIndex] === 'true' ? 'true' : 'false');
        } catch (error) {
          return T(record[dataIndex] === 'true' ? 'true' : 'false');
        }
      } else if (column.type === 'upload') {
        return <Upload onlyShowList value={record[dataIndex] || []} options={{ downloadUrl: column.options.downloadUrl }} />;
      } else if (column.type === 'formFiled' && column.options?.scriptText) {
        // 脚本类型需要渲染
      } else if (column.type === 'input') {
        return <span style={{ textAlign: column.textAlign, display: 'inline-block', width: '100%' }} >{record[dataIndex]}</span>;
      } else {
        return record[dataIndex];
      }
    }


    // eslint-disable-next-line eqeqeq
    let value = record[dataIndex];

    if (column.type !== 'datePicker') {
      value = value || record[dataIndex] == 0 ? record[dataIndex] : column.options?.isInitialValue ? moment().format(column.options?.format) : undefined;
    }


    if ((column.type === "select" || column.type === "radio") && !value) {
      value = column.options.dataSource.filter((item: any) => item.checked)?.[0]?.value;
    } else if (column.type === "checkbox" && !value) {
      value = column.options.dataSource.filter((item: any) => item.checked).map((item: any) => item.value);
    }

    const options = {
      enviromentConfig,
      value,
      size: 'small' as any,
      _dataIndex: dataIndex,
      disabled: inEditInitVal ? false : column.disabled,
      onValuesChange: props.onValuesChange,
      setActionFiledMap: props.setActionFiledMap,
      onChange: (e: any, isInitPeriod?: boolean) => {
        if (props.isDesign) return; // 设计模式下 不处理
        let v = typeof e === 'object' && !Array.isArray(e) ? e?.target?.value : e;
        onChangeLine(record, v === undefined || v === null ? "" : v, dataIndex, isInitPeriod);
      },
      onDataLinkComBoxChange: (e: any, extraFieldName?: string[]) => {
        if (props.isDesign) return; // 设计模式下 不处理

        const index = dataSource.findIndex((item) => item.id === record.id);
        let key = column.dataIndex;

        currChangeDataIndex.current = key;
        currChangeLineIndex.current = index;

        let bindList = realColumns.filter(
          (item) => (linkArray.includes(item.type)) && item?.options?.bindName === key
        );

        const mapFileds = column.options.mapFileds || {};
        const filedShowName = Array.isArray(column.options?.filedShowName) ? column.options?.filedShowName : [{ value: column.options?.filedShowName }];
        let _temp = filedShowName.reduce((all: object, now: any) => {
          return { ...all, [mapFileds[now.value] || now.value]: e[now.value] || '' };
        }, {});

        // 处理value值
        _temp[dataIndex] = e?.[filedShowName[0]?.value] || '';

        extraFieldName?.forEach(item => {
          _temp[mapFileds[item] || item] = e?.[item];
        });

        bindList.forEach((item: any) => {
          if (['input', 'inputNum'].includes(item.type)) {
            _temp[item['dataIndex']] = e?.[item?.options?.showFiled] || '-';
          } else {
            _temp[item['dataIndex']] = '';
            _temp = filedShowName.reduce((all: object, now: any) => {
              return { ...all, [now.value]: '' };
            }, _temp);
          }
        });

        setTimeout(() => {
          isInitial.current = true;
          setDataSource(prev =>
            prev.map((item: any, i: number) => {
              return i === index ? { ...item, ..._temp } : item;
            })
          );
        }, 200);
      },
      onDataLinkChange: (e: any, v: string) => {
        if (props.isDesign) return; // 设计模式下 不处理

        const index = dataSource.findIndex((item) => item.id === record.id);
        let key = column.dataIndex;

        currChangeDataIndex.current = key;
        currChangeLineIndex.current = index;

        let bindList = realColumns.filter(
          (item) => (linkArray.includes(item.type)) && item?.options?.bindName === key
        );

        let _temp = { ...e };

        _temp[dataIndex] = e?.[column.options?.showFieldName] || '';


        bindList.forEach((item: any) => {
          if (['input', 'inputNum'].includes(item.type)) {
            _temp[item['dataIndex']] = e?.[item?.options?.showFiled] || '-';
          } else {
            _temp[item['dataIndex']] = '';
            // 表格内的字段一并清除
            _temp = item.options?.filedShowName.reduce((all: object, now: any) => {
              return { ...all, [now.value]: '' };
            }, _temp);
          }
        });
        // isInitial.current = true;
        setTimeout(() => {
          isInitial.current = true;
          setDataSource(prev =>
            prev.map((item: any, i: number) => {
              return i === index ? { ...item, ..._temp, _isImport: undefined, [dataIndex]: v } : item;
            })
          );
        }, 200);
      },
      index,
      record,
      item: dataSource[index],
      _columns: column,
      key: column.key,
      scriptsChangeData,
      getCurrInterceptors,
      inEditInitVal,
      options: { ...column.options, radio: column?.radio },
      columns: inEditInitVal ? realColumns?.map(item => ({ ...item, disabled: false })) : realColumns,
      validateFields: props.validateFields,
      controlRefs: props.controlRefs,
      showModal: (options: ShowModalOptionsType) => props.showModal?.(options, props._id)
    };

    const Component = ControlMap[column.type] || Input;
    return <Component {...options} />;
  };


  const components = useMemo(() => {
    return {
      header: {
        cell(props: any) {
          const dataIndex = props.className?.split(" ")[1];
          const column = realColumns.find(item => item.dataIndex === dataIndex);
          const _style: Record<string, any> = { ...props.style };

          if (column?.customizeStyleFlag) {
            if (column?.fontSize) _style.fontSize = column.fontSize;
            if (column?.backgroundColor) _style.backgroundColor = column.backgroundColor;
            if (column?.fontWeight) _style.fontWeight = column.fontWeight;
            if (column?.color) _style.color = column.color;
          }

          return (
            <th {...props} style={_style} />
          );
        },
      },
    };
  }, [realColumns]);

  const paginationChange = (page: number, _pageSize: number | undefined) => {
    const nextPage = _pageSize !== pageSize ? 1 : page;
    setPage(nextPage);

    if (_pageSize) {
      setPageSize(_pageSize);
    }

  };

  const customPage = useMemo(() => {
    return (canvasProps.isDesign ? designDefData : dataSource).slice((page - 1) * pageSize, page * pageSize) || [];
  }, [dataSource, pageSize, page, designDefData, canvasProps.isDesign]);

  const changeSummaryValue = (e: React.BaseSyntheticEvent, name: string) => {
    if (!name) return;

    summaryValueRef.current = {
      ...summaryValueRef.current,
      [name]: e.target.value
    };

    setSummaryValue(summaryValueRef.current);
    props.onValuesChange?.(props.name + '.summary.' + name, summaryValueRef.current, false);
  };

  const pagination = {
    showSizeChanger: true,
    showTotal: (total: number) => `${total} total`,
    pageSize,
    pageSizeOptions,
    total: dataSource.length,
    current: page,
    onChange: paginationChange,
  };

  const _scrollStyle = {
    ...scrollStyle,
    y: typeof props.scrollY === 'number' ? props.scrollY : undefined
  };

  const onOk = async (data: any[], type: string) => {
    setVisible(false);

    if (scriptText) {
      const values = await validateFields?.(false);

      const refsKey = Object.keys(controlRefs as any);
      const refDataList: any = [];

      if (refsKey.length) {
        for (let item of refsKey) {
          if (controlRefs?.[item]?.onListRefresh) {
            refDataList.push(controlRefs?.[item]);
          }
          refDataList[item] = controlRefs?.[item];
        }
      }

      evalScriptText({
        scriptText,
        extra: {
          _OBJ1_: values,
          _OBJ_: data,
          _TYPE_: type,
          _REFS_: refDataList
        },
        next: (result: any, actionFiled?: ActionFieldType) => {
          setDataSource(result?.[props.name!] || []);

          if (actionFiled) {
            setActionFiledMap?.((prev: ActionFieldType) => {
              return { ...prev, ...actionFiled };
            });
          }
        }
      });
    };
  };

  async function actionClick(scriptText: string, record?: any) {
    if (scriptText) {
      const values = await props.validateFields?.(false, undefined, false);
      if (record) values._record = record;
      const refsKey = Object.keys(props.controlRefs as any);
      const refDataList: any = [];

      if (refsKey.length) {
        for (let item of refsKey) {
          if (props.controlRefs?.[item]?.onListRefresh) {
            refDataList.push(props.controlRefs?.[item]);
          }
        }
      }

      evalScriptText({
        scriptText,
        extra: {
          _OBJ_: record,
          _OBJ1_: values,
          _ENV_: props?.enviromentConfig || {},
          _REFS_: refDataList,
          showModal: (options: ShowModalOptionsType) => props.showModal?.(options, props._id + '_others'),
          parentNext: props.parentNext
        },
        next: (result: any, actionFiled?: ActionFieldType) => {
          if (result) {
            props.setScriptsChangeData?.(result);
            props.emitControlChangeValue?.();
          }

          if (actionFiled) {
            setActionFiledMap?.((prev: ActionFieldType) => {
              return { ...prev, ...actionFiled };
            });
          }
        }
      });
    }
  }

  function setSummaryInputStyle(el: InputRef | null, v: SummaryType) {
    if (el && el.input) {
      const _style = v.name ? summaryStyles[v.name] : v.style;
      for (let k in _style) {
        el.input.style.setProperty(k, _style[k], 'important');
      }
    }
  }

  return (
    <div {...canvasProps} className={`fdTable ${cls.table}`}>
      <Row justify="space-between" align="middle" style={rowStyle}>
        <Col style={{
          ...colStyle, ...(tableProps.bigTitle ? {
            fontWeight: 'bold'
          } : {})
        }}>{textReplaceStr(localStorage.i18nextLng === 'en' ? titleEn! : title!, scriptsChangeData!)}</Col>
        <Col>
          {!disabled && <>

            {
              tableProps?.btnGroup?.map((item) => (
                <Button
                  {...item}
                  style={{ marginRight: '8px' }}
                  onClick={() => actionClick(item.scriptText!)} >
                  {localStorage.i18nextLng === 'en' ? item?.textEn : item?.text}
                </Button>
              ))
            }
            {tableProps.bacthUploadData && !customOptions.exportBtn?.hide &&
              <>
                <Button style={{ marginRight: '8px' }} onClick={downLoadTemplate} disabled={canvasProps.isDesign} type="primary">
                  {localStorage.i18nextLng === 'en' ? 'Download Import Template' : '下载导入模板'}
                </Button>
                {!customOptions.importBtn?.hide && (
                  <Button style={{ marginRight: '8px' }} onClick={() => scriptText ? setVisible(true) : inputRef.current?.click()} disabled={canvasProps.isDesign} type="primary">
                    {localStorage.i18nextLng === 'en' ? 'Import Data' : '导入数据'}
                    <input onChange={onChange} ref={inputRef} style={inputStyle} type='file' accept='.xlsx' />
                  </Button>
                )}
              </>
            }
            {!hideAdd && !customOptions.addBtn?.hide && <Button onClick={addLine} disabled={canvasProps.isDesign} type="primary">
              <Icon icon="&#xe635;" style={{ marginRight: '6px', fontSize: '16px' }} /> {T('add')}
            </Button>}
          </>}
        </Col>
      </Row>
      <Table
        scroll={_scrollStyle}
        pagination={false}
        dataSource={customPage}
        components={components}
        summary={() => {
          if (!summaryData.length) return null;
          return (
            <>
              {summaryData.map((item, index) => (
                <Table.Summary.Row key={index}>
                  {item.map((v, vi) => (
                    <Table.Summary.Cell index={vi} key={vi} colSpan={v.colSpan}>
                      {v.editable ? (
                        <Input
                          disabled={v.disabled}
                          size='small'
                          value={summaryValue[v.name]}
                          onChange={e => changeSummaryValue(e, v.name)}
                          ref={el => setSummaryInputStyle(el, v)} />
                      ) : (
                        <span style={v.name ? summaryStyles[v.name] : v.style}>
                          {v.name ? summaryValue[v.name] : v.value}
                        </span>
                      )}
                    </Table.Summary.Cell>
                  ))}
                </Table.Summary.Row>
              ))}
            </>
          );
        }}>
        {tableProps.showItemNo && (
          <Column ellipsis width={60} title={T('Item No')} key="itemNo" render={(text, record, index) => <span>{(index + 1) * 10}</span>} />
        )}
        {_columns?.filter(item => canvasProps.isDesign ? true : !item.hideInput).map((item) => (
          <Column
            className={item.dataIndex as string}
            width={+(item.width || 100)}
            title={
              !item.options?.required ? (localStorage.i18nextLng === 'en' ? item?.titleEn : item.title) : <span>{item.type !== "formFiled" && <span style={requiredStyle}>*</span>}{(localStorage.i18nextLng === 'en' ? item?.titleEn : item.title)}</span>
            }
            key={item.key}
            render={(text, record) => render(text, record, item as ColumnType)} />
        ))}
        {!disabled && !props.isDesign && !hideDelete && !customOptions.columnDelete?.hide && (
          <Column<DataItemProps>
            fixed='right'
            title={T('action')}
            width={60}
            render={(text, record) =>
              record._disabled === true || (Array.isArray(record._disabled) && record._disabled.includes('action')) ? null : (
                <ActionText.Delete onClick={() => delLine(record.id, customPage.length)} />
              )
            }
          />
        )}
      </Table>
      {dataSource.length > PAGE_SIZE && <Pagination {...pagination} />}
      <FileModal onOK={onOk} visible={visible} onCancel={() => setVisible(false)} />
    </div>
  );
});
